package com.yyg.ssm.shiro;

import com.yyg.ssm.domain.User;
import com.yyg.ssm.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import javax.print.attribute.standard.PrinterInfo;
import java.util.List;

/**
 * @Author: 一一哥
 * @Blame: yyg
 * @Since: Created in 2021/1/6
 * @Description: $cursor$
 */
public class MyRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    /**
     * 认证方法:负责登录的业务逻辑.
     * AuthenticationToken:认证令牌.
     * AuthenticationInfo:认证信息
     * <p>
     * Throwable--->error/exception....
     * 运行时异常:受检时异常/非受检时异常.
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //接收token,进行身份的验证...
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String username = token.getUsername();

        //面试题:为什么密码是char[]类型?为什么不是String类型?
        //String pwd="123";
        //String pwd="";
        //char p=1;
        //char p=0;
        char[] password = token.getPassword();

        User user = userService.login(username);
        if (user == null) {
            //如果返回值为null,则会抛出一个AuthenticationException异常!
            return null;
        }

        //这里进行密码校验
        if (!user.getPassword().equals(String.valueOf(password))) {

            return null;
        }

        //保存用户信息到session中
        Session session = SecurityUtils.getSubject().getSession();
        session.setAttribute("user", user);

        //SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(username,password,getName());
        return new SimpleAuthenticationInfo(user, password, getName());
    }

    /**
     * 授权方法:授权的前提是已经经过认证了....只有某些资源需要授权时才会调用方法.
     * PrincipalCollection:得到一个身份的集合.
     * AuthorizationInfo:授权信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取身份信息
        //User user = (User) principalCollection.getPrimaryPrincipal();
        User user = (User) super.getAvailablePrincipal(principalCollection);

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        //根据用户名/id查询对应的角色
        List<String> roles = userService.selectRolesByUid(user.getId());
        //添加角色
        info.addRoles(roles);

        //根据用户名/id查询对应的权限
        List<String> permissions = userService.selectPermissionsByUid(user.getId());
        //添加权限
        info.addStringPermissions(permissions);

        return info;
    }

}
